import numpy as np
import copy
import util.data_helper as data_helper
# import deeptriage.BiRNN_msg as BiRNN_msg
'''
为第0个窗口指定代价向量组合
'''

def get_cost_matrix():
	solution_size = 32
	file = '../data/windows/window_0_all.txt'
	developer_file = '../data/windows/developer_window_0.txt'

	origin_cost_vector = []
	cost_matrix = []

	developers_dis = []     #[开发者name, 开发者修复的bug个数]
	with open(file, 'r') as reader:
		for line in reader.readlines():
			temp = line.strip().split('\t')
			developers_dis.append([temp[0], int(temp[1])])

	# 划分开发者修复bug数量的数量级，根据数量级定义误分类代价
	cost_value = {}
	for i in range(len(developers_dis)):
		name = developers_dis[i][0]
		num = developers_dis[i][1]
		if num > 0 and num <= 50:
			cost_value[name] = 0.8
		elif num > 50 and num <= 100:
			cost_value[name] = 0.7
		elif num > 100 and num <= 200:
			cost_value[name] = 0.6
		elif num > 200 and num <= 300:
			cost_value[name] = 0.5
		elif num > 300 and num <= 400:
			cost_value[name] = 0.4
		elif num > 400:
			cost_value[name] = 0.3

	# print(cost_value)
	# 按照developer_window_0.txt，根据代价向量，按开发者的顺序填充代价矩阵
	developers = []
	with open(developer_file, 'r') as reader:
		for line in reader.readlines():
			name = line.strip()
			developers.append(name)
			origin_cost_vector.append(cost_value[name])

	# print(origin_cost_vector)
	# 把代价向量扩展成代价矩阵，注意相应位置的误分类代价置为0

	# 其实我对这里代价向量的处理是有些疑惑的，有两种处理方式，一种对于每个类别的误分类代价，只关注分对（0）和分错的情况，而不管它被错分给谁了
	# 另一种是关注每个类别被错分给谁了，但是每个类别的误分类向量都保持相同，只是彼此分对的时候才改动为0。。。。感觉上后者这种情况好像从逻辑和可能造成的后果上，并站不住脚。。

	# 这是后者的写法，行之间基本都是相同的，只是对角线置为0
	# for i in range(len(developers)):
	# 	cost_matrix.append(copy.deepcopy(origin_cost_vector))
	# 	cost_matrix[i][i] = 0      # 分对的话就没有误分类代价

	# 这是前者的写法，每行的子元素相同
	for i in range(len(developers)):
		# name = developers[i]
		cost_matrix.append([origin_cost_vector[i] for _ in range(len(developers))])
		cost_matrix[i][i] = 0
		cost_matrix[i].insert(0,0)
		cost_matrix[i].insert(0,0)

	# for i in range(len(developers)):
	# 	print(cost_matrix[i])
	# print(cost_matrix)
	return cost_matrix
# BiRNN_msg.main(cost_matrix)

def implement_random_cost_matrix(developer_size):
	'''
	这个没什么用讲真，就是不想改变原始模型的结构，又想不加入代价敏感矩阵，所以解决方法就是自定义一个代价矩阵
	:param developer_size: 
	:return: 
	'''
	# cost_matrix = np.array([0 for _ in range(developer_size)])
	# for i in range(developer_size):             # 在不考虑代价敏感的一般情况下，对角线元素=0，非对角线=1
		# temp = [1 for _ in range(developer_size)]
		# temp[i] = 0
		# cost_matrix.append(temp)
	cost_matrix = 1-np.eye(developer_size, dtype=int)         # 为1的对角阵
	return cost_matrix

def get_cost_matrix_from_file(D):
	x = []
	# with open('../data/final/optimal_cost_matrix_1540907148.txt', 'r') as reader:
	with open('/home/wanglinhui/optimal_cost_matrix.txt', 'r') as reader:
		for line in reader.readlines():
			x.append(float(line.strip()))

	# cost_matrix = [[x[i]/len(x) for i in range(len(x))] for _ in range(len(x))]
	# cost_matrix = [[0 for _ in range(D)] for _ in range(D)]
	# x = np.array(list(x)*D).reshape((D, D)).tolist()      # 注意这里的d-1
	x = np.array(x).reshape((D, D-1)).tolist()      # 注意这里的d-1
	for i in range(D):
		x[i].insert(i, 0)           # 对角线位置插入0
		# x[i][i]=0          # 对角线位置插入0
	cost_matrix = x
	# cost_matrix[0] = x
	# x = []
	# cost_matrix = [[0 for _ in range(D)] for _ in range(D)]
	# # with open('../data/final/optimal_cost_matrix.txt', 'r') as reader:
	# with open('/home/wanglinhui/optimal_cost_matrix_1540907148.txt', 'r') as reader:
	# # with open('/home/wanglinhui/PycharmProjects/2LSTM/deeptriage/runs/1540807878/optimal_cost_matrix_2.txt', 'r') as reader:
	# 	for line in reader.readlines():
	# 		x.append(float(line.strip()))
	# sign = 0  # 计数，顺序输出x
	# for i in range(D):
	# 	for j in range(D):
	# 		cost_matrix[i][j] = x[sign]
	# 		if i == j:
	# 			cost_matrix[i][j] = 0  # 指定位置置为0，即对角线位置
	# 		# mis_vector.insert(i, 0)     # 在指定位置插入0，作为新增对角线
	# 		sign += 1  # 相当于.next()
	return cost_matrix

def get_cost_matrix_from_data_distribution():
	'''
	应该是基于训练集中的样本数量,取得cost 矩阵的初始分布
	:return:
	'''
	bug_msg_all, _ = data_helper.get_msg_all()
	time_windows = data_helper.split_dataset_by_eight_to_two(bug_msg_all)
	developers = data_helper.create_developers_list()
	D = len(developers)
	# 统计训练集中每类样本的数量，以数量定代价矩阵的初始分布
	fixed_by_developers = [0 for _ in range(len(developers))]

	for bugid in time_windows[0]:
		value = bug_msg_all[bugid]
		fixed_by_developers[developers.index(value[0])] += 1
	max_num = max(fixed_by_developers)
	# 将频数矩阵归一化
	fixed_by_developers = [fixed_by_developers[i] / max_num for i in range(len(fixed_by_developers))]
	# 塑造代价矩阵,应该是将列向量扩展开
	m = np.mean(fixed_by_developers)		# 归一化处理
	max_num = np.max(fixed_by_developers)
	min_num = np.min(fixed_by_developers)
	# 第一种归一化方式
	# fixed_by_developers = [(fixed_by_developers[i] - m) / (max_num - min_num) for i in range(len(fixed_by_developers))]
	# 第二种归一化方式
	fixed_by_developers = [fixed_by_developers[i] / max_num for i in range(len(fixed_by_developers))]
	cost_matrix = np.array((fixed_by_developers)*D).reshape((D, D)).tolist()  # 得到真实的cost矩阵，C{i，j}表示i类样本被分成j类的代价
	for i in range(D):
		cost_matrix[i][i]=0          # 对角线位置置为0
	return np.array(cost_matrix).T

if __name__ == '__main__':
    # print(implement_random_cost_matrix(342))
    print(get_cost_matrix_from_file(342))

